<script setup lang="ts">
import type { PgsqlEnvStore } from "./pgsql-env-store.ts";
import { SettingFilled } from "@ant-design/icons-vue";
import SectionCard from "@/components/app/section-card.vue";
import { computed, ref, watch } from "vue";
import type { LocalVersionItem } from "@/modules/dev-env/common/types.ts";
import FolderPickerInput from "@/components/framework/folder-picker-input.vue";
import path from "@/framework/util/path.ts";
import { execInTerminal } from "@/util/system-utils2.ts";
import WindowsServiceButton from "@/modules/dev-env/components/windows-service-button.vue";
import type { PgDevilConfig } from "@/modules/dev-env/database/pgsql/types.ts";
import { showMessageAndPrint } from "@/framework/util/log.ts";
import { message } from "ant-design-vue";
import OpenFileButton from "@/modules/dev-env/components/open-file-button.vue";
import { ConfigUtils } from "@/util/config-utils.ts";
import ConfirmButton from "@/components/framework/confirm-button.vue";
import { DevilInstallTree, EnvTree } from "@/modules/dev-env/common/tree.ts";

const { store } = defineProps<{
  store: PgsqlEnvStore;
}>();

// 当前操作版本
const version = computed<LocalVersionItem | null>(() => store.selectedItem);
// 配置文件
const configFilePath = computed(() => (version.value ? path.join(version.value.installPath, DevilInstallTree.configFile) : ""));
// 数据库配置
const pgConfig = ref<PgDevilConfig>({});
// 初始化命令行选项
const initOptions = ref("--auth=password --encoding=UTF8 --locale=Chinese -W");

const canRunPgCtl = computed(() => !!pgConfig.value.dataDir);
const canRunWinSrv = computed(() => !!pgConfig.value.dataDir && !!pgConfig.value.serviceName);

const saveDevilConfig = () => {
  if (!configFilePath.value) return;
  const configContent = JSON.stringify(pgConfig.value, null, 2);
  native.fs.writeFile(configFilePath.value, configContent).catch(showMessageAndPrint);
};

const getDefaultDataPath = (version: LocalVersionItem) => {
  // 以主要版本为默认数据目录, eg: pgsql-16
  const [major] = version.version.split(".");
  return path.join(store.installDir, EnvTree.dataDir, `pgsql-${major}}`);
};
watch(
  version,
  async value => {
    if (value) {
      const config = (await native.fs.readFileJson<PgDevilConfig>(configFilePath.value)) || {};
      config.dataDir ||= getDefaultDataPath(value);
      config.serviceName ||= "PostgreSQL";
      config.username ||= "postgres";
      pgConfig.value = config;
    }
  },
  { immediate: true },
);

const execCmd = (cmd: string, keep = true, sudo = false) => {
  console.log("[pgsql-settings] exec cmd >", cmd);
  execInTerminal(cmd, { cwd: version.value!.installPath, subPath: ["bin"], sudo, keep });
};

const isInstalled = async () => {
  const dataDir = pgConfig.value.dataDir;
  if (!dataDir) return false;
  if (await native.fs.exists(dataDir)) {
    const files = await native.fs.readdir(dataDir);
    if (files.length > 0) {
      return true;
    }
  }
  return false;
};

const initDatabase = async () => {
  if (await isInstalled()) {
    return void message.error("数据目录不为空");
  }
  const cfg = pgConfig.value;
  execCmd(`initdb --pgdata="${cfg.dataDir}" --username=${cfg.username} ${initOptions.value}`);
  saveDevilConfig();
};

const runPgCtl = async () => {
  if (!(await isInstalled())) return void message.error("请先初始化数据库");
  const cfg = pgConfig.value;
  const cmds = ["pg_ctl", `--pgdata="${cfg.dataDir}"`, cfg.runOptions, "start"];
  execCmd(cmds.filter(it => !!it).join(" "), false);
  saveDevilConfig();
};

const connectDb = async () => {
  if (!(await isInstalled())) return void message.error("请先初始化数据库");
  const cfg = pgConfig.value;
  const port = (await ConfigUtils.readSimpleConf(path.join(cfg.dataDir, "postgresql.conf"), "port")) || "5432";
  execCmd(`psql -h localhost -p ${port} -U ${cfg.username}`);
};

const installService = async () => {
  if (!(await isInstalled())) return void message.error("请先初始化数据库");
  const cfg = pgConfig.value;
  execCmd(`pg_ctl register -N ${cfg.serviceName} -D "${cfg.dataDir}"`, true, true);
};
const uninstallService = async () => {
  execCmd(`pg_ctl unregister -N ${pgConfig.value.serviceName}`, true, true);
};
</script>

<template>
  <section-card :icon="SettingFilled">
    <template #title>
      <span>配置/安装</span>
      <span v-if="version" class="color-text-secondary">{{ version.installPath }}</span>
    </template>

    <div v-if="version" class="full-view overflow-y-auto p-10">
      <a-form :label-col="{ span: 5 }" :wrapper-col="{ span: 17 }" :disabled="!version">
        <a-divider orientation="left">
          <span class="color-text-secondary font-14">数据库配置</span>
        </a-divider>
        <a-form-item label="数据目录" required>
          <folder-picker-input v-model:value="pgConfig.dataDir" />
        </a-form-item>
        <a-form-item label="数据库超级用户名" required>
          <a-input v-model:value="pgConfig.username" class="w-200" />
        </a-form-item>
        <a-form-item label="初始化命令行其他选项(initdb)">
          <a-input v-model:value="initOptions" />
        </a-form-item>
        <a-form-item label=" " :colon="false">
          <a-space>
            <a-button :disabled="!canRunPgCtl" @click="initDatabase">初始化数据库</a-button>
            <open-file-button :dir="pgConfig.dataDir" file="postgresql.conf">编辑配置文件</open-file-button>
          </a-space>
        </a-form-item>

        <a-divider orientation="left">
          <span class="color-text-secondary font-14">数据库控制</span>
        </a-divider>
        <a-form-item label="运行命令行参数(pg_ctl)" help="--pgdata使用上面的配置,这里不用输入">
          <a-input v-model:value="pgConfig.runOptions" />
        </a-form-item>
        <a-form-item label=" " :colon="false">
          <a-space>
            <a-button :disabled="!canRunPgCtl" @click="runPgCtl">启动服务</a-button>
            <a-button :disabled="!canRunPgCtl" @click="connectDb">连接数据库</a-button>
          </a-space>
        </a-form-item>

        <a-divider orientation="left">
          <span class="color-text-secondary font-14">Windows服务</span>
        </a-divider>
        <a-form-item label="服务名称">
          <a-input v-model:value="pgConfig.serviceName" placeholder="请输入服务名称" />
        </a-form-item>
        <a-form-item label=" " :colon="false">
          <a-space>
            <a-button :disabled="!canRunWinSrv" @click="installService">安装</a-button>
            <confirm-button :disabled="!canRunWinSrv" content="确定要卸载吗？" @ok="uninstallService">卸载</confirm-button>
            <windows-service-button :service-name="pgConfig.serviceName" :disabled="!canRunWinSrv" />
            <windows-service-button :service-name="pgConfig.serviceName" :disabled="!canRunWinSrv" action="stop" danger />
          </a-space>
        </a-form-item>
      </a-form>
    </div>

    <div v-else class="full flex-center flex-dc">
      <p class="color-text-secondary">请选择配置版本</p>
      <p class="color-text-tertiary">下拉菜单 > "配置/安装"</p>
    </div>
  </section-card>
</template>

<style scoped lang="less"></style>
